package com.candoit.webapps.pricing.util.spreadsheet;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.candoit.webapps.pricing.model.Categoria;
import com.candoit.webapps.pricing.model.CategoriaCuenta;
import com.candoit.webapps.pricing.model.CentroCostos;
import com.candoit.webapps.pricing.model.CriterioDistribucion;
import com.candoit.webapps.pricing.model.Cuenta;
import com.candoit.webapps.pricing.model.CuentaMes;
import com.candoit.webapps.pricing.util.QueryUtil;

public class CommandBDIForSpreadsheet {

	private Map<CriterioDistribucion, Map<CentroCostos, Double>> matriz_proporcion_criterio_cc;
	private Map<Cuenta, Map<CentroCostos, Double>> matrizCosto;
	private Map<CentroCostos, Map<CentroCostos, Double>> ccppdCosto;
	private Map <CentroCostos,Double> totalesProrrateoPP;
	private Map<CategoriaCuenta, Map<Cuenta,Double>> categoriasMap;
	private List<CentroCostos> centros;
	
	public CommandBDIForSpreadsheet(Map<CriterioDistribucion, Map<CentroCostos, Double>> matriz_proporcion_criterio_cc){
		this.matriz_proporcion_criterio_cc = matriz_proporcion_criterio_cc;
		initCategorias();
		initCentrosDeCostosIndustriales();
		initMatrizCostos();
		initCCPPDCostos();
	}
	
	public Double getCost(Cuenta cu, CentroCostos cc){
		return matrizCosto.get(cu).get(cc);
	}
	
	private void initCCPPDCostos(){
		totalesProrrateoPP = costosTotalesCCPP();
		ccppdCosto = new HashMap<CentroCostos, Map<CentroCostos, Double>>();
		
		for (CentroCostos cc : totalesProrrateoPP.keySet()){
			Double totalCuenta = totalesProrrateoPP.get(cc);
			CriterioDistribucion c = cc.getCriterio();
			Map<CentroCostos, Double> maux = new HashMap<CentroCostos, Double>();
			for (CentroCostos maquina : centros){
				Double proporcion = getProporcion(c, maquina);
				maux.put(maquina, totalCuenta*proporcion);				
			}
			ccppdCosto.put(cc, maux);
		}
		
	}
	
	private void initMatrizCostos(){
		matrizCosto = new HashMap<Cuenta, Map<CentroCostos, Double>>();
		
		for (CategoriaCuenta ca : categoriasMap.keySet()){
			for (Cuenta cu : categoriasMap.get(ca).keySet()){
				Map<CentroCostos, Double> maux = new HashMap<CentroCostos, Double>();
				if (categoriasMap.get(ca).containsKey(cu)){	
					Double totalCuenta = categoriasMap.get(ca).get(cu);
					CriterioDistribucion c = cu.getCriterio();
					for (CentroCostos cc : centros){
						Double proporcion = getProporcion(c, cc);
						maux.put(cc, totalCuenta*proporcion);	
					}
					matrizCosto.put(cu, maux);
				}
			}
		}
		
	}
	
	private Map <CentroCostos,Double> costosTotalesCCPP(){
		Integer categoria = Categoria.SERVICES_CODE;
		Map <CentroCostos,Double> costosTotalesCCPP = new HashMap<CentroCostos, Double>();
		
		List<Cuenta> cuentas = QueryUtil.getInstance().getCuentas();
		List<CentroCostos> paraProductivos = QueryUtil.getInstance().getCentroCostosByCategoria(categoria); 
		
		/*inicializo el mapa*/
		for(CentroCostos cc : paraProductivos){
			costosTotalesCCPP.put(cc, 0.0d);
		}
		
		for (Cuenta cu : cuentas){
			CuentaMes cum = QueryUtil.getInstance().getUltimaCuenta(cu);
			if (cum != null){	
				Double totalCuenta = cum.getCosto();
				CriterioDistribucion c = cu.getCriterio();
			
				for(CentroCostos cc : paraProductivos){
					Double proporcion = getProporcion(c, cc);
					costosTotalesCCPP.put(cc, costosTotalesCCPP.get(cc) + totalCuenta*proporcion);
				}
			}	
		}
		return costosTotalesCCPP;
	}
	
	private Double getProporcion(CriterioDistribucion c, CentroCostos cc){
		Double proporcion = 0.0d;
		try {
			proporcion = matriz_proporcion_criterio_cc.get(c).get(cc);
		} catch (Exception e) {
		}
		return proporcion;
	}
	
	private void initCentrosDeCostosIndustriales(){
		centros = new ArrayList<CentroCostos>();
		centros = QueryUtil.getInstance().getCentroCostosByCategoria(Categoria.PRODUCTION_CODE);
	}
	
	/*inicializa un mapa con clave categorias y como valor una lista de sus cuentas*/
	private void initCategorias(){
		categoriasMap = new HashMap<CategoriaCuenta, Map<Cuenta,Double>>();
		
		List<CategoriaCuenta> categorias = QueryUtil.getInstance().getAllCategoriaCuentas();
		
		for(CategoriaCuenta c : categorias){
			List<Cuenta> cuentas = QueryUtil.getInstance().getAllCuentasByCategoria(c);
			if(cuentas != null){
				Map<Cuenta,Double> maux = new HashMap<Cuenta,Double>();
				for(Cuenta cu : cuentas){
					CuentaMes cum = QueryUtil.getInstance().getUltimaCuenta(cu);
					if (cum != null){	
						maux.put(cu, cum.getCosto());
					}
				}
				categoriasMap.put(c, maux);
			}
		}
	}

	public Map<CategoriaCuenta, Map<Cuenta,Double>> getCategoriasMap() {
		return categoriasMap;
	}

	public List<CentroCostos> getCentros() {
		return centros;
	}
	
	public Map<CentroCostos, Map<CentroCostos, Double>> getCcppdCosto() {
		return ccppdCosto;
	}

	public Map<CentroCostos, Double> getTotalesProrrateoPP() {
		return totalesProrrateoPP;
	}

	/*TODO: llevar a libreria o usar otro metodo*/
//	private Integer mesActual(){
//		Calendar cal = new GregorianCalendar();
//		Date fechaActual = new Date();
//		cal.setTime(fechaActual);
//		Integer mesActual = cal.get(Calendar.MONTH);
//		List<CuentaMes> cuentas = QueryUtil.getInstance().getCuentasByMes(mesActual);
//        if (cuentas == null || cuentas.isEmpty()){
//                if (mesActual != 0){
//                        mesActual = mesActual -1;
//                }else{
//                        mesActual = 11;
//                }
//        }
//		return mesActual;
//	}
	
}
